//
//  SPGameManager.h
//  ShandongPoker
//
//  Created by Developer on 2025-01-08.
//  Copyright © 2025 ShandongPoker. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "SPPlayer.h"
#import "SPDeck.h"
#import "SPHandEvaluator.h"
#import "../../Core/Utils/SPConstants.h"

NS_ASSUME_NONNULL_BEGIN

@class SPGameManager;

/**
 * 游戏管理器代理协议
 */
@protocol SPGameManagerDelegate <NSObject>

@optional

/**
 * 游戏状态变化回调
 * @param manager 游戏管理器
 * @param newState 新状态
 */
- (void)gameManager:(SPGameManager *)manager didChangeState:(SPGameState)newState;

/**
 * 玩家行动回调
 * @param manager 游戏管理器
 * @param player 行动玩家
 * @param action 行动类型
 * @param amount 行动金额
 */
- (void)gameManager:(SPGameManager *)manager 
         playerDidAct:(SPPlayer *)player 
               action:(SPPlayerAction)action 
               amount:(NSInteger)amount;

/**
 * 发牌回调
 * @param manager 游戏管理器
 * @param player 接收玩家
 * @param cards 发出的牌
 */
- (void)gameManager:(SPGameManager *)manager 
         didDealCards:(NSArray<SPCard *> *)cards 
              toPlayer:(SPPlayer *)player;

/**
 * 公共牌更新回调
 * @param manager 游戏管理器
 * @param cards 公共牌
 * @param round 当前轮次
 */
- (void)gameManager:(SPGameManager *)manager 
    didUpdateCommunityCards:(NSArray<SPCard *> *)cards 
                      round:(SPGameState)round;

/**
 * 游戏结束回调
 * @param manager 游戏管理器
 * @param winner 获胜者
 * @param winAmount 获胜金额
 * @param winningHand 获胜牌型
 */
- (void)gameManager:(SPGameManager *)manager 
           gameDidEnd:(SPPlayer * _Nullable)winner 
            winAmount:(NSInteger)winAmount 
          winningHand:(SPHandResult * _Nullable)winningHand;

@end

/**
 * 德州扑克游戏管理器
 * 负责游戏逻辑控制和状态管理
 */
@interface SPGameManager : NSObject

#pragma mark - 属性

/// 游戏管理器代理
@property (nonatomic, weak, nullable) id<SPGameManagerDelegate> delegate;

/// 当前游戏状态
@property (nonatomic, assign, readonly) SPGameState gameState;

/// 当前底池金额
@property (nonatomic, assign, readonly) NSInteger currentPot;

/// 当前轮次
@property (nonatomic, assign, readonly) NSInteger currentRound;

/// 小盲注金额
@property (nonatomic, assign, readonly) NSInteger smallBlind;

/// 大盲注金额
@property (nonatomic, assign, readonly) NSInteger bigBlind;

/// 当前需要跟注的金额
@property (nonatomic, assign, readonly) NSInteger currentCallAmount;

/// 最小加注金额
@property (nonatomic, assign, readonly) NSInteger minRaiseAmount;

/// 庄家位置
@property (nonatomic, assign, readonly) NSInteger dealerPosition;

/// 当前行动玩家位置
@property (nonatomic, assign, readonly) NSInteger activePlayerPosition;

/// 是否游戏暂停
@property (nonatomic, assign, readonly) BOOL isPaused;

#pragma mark - 玩家数据

/// 所有玩家列表
@property (nonatomic, strong, readonly) NSArray<SPPlayer *> *players;

/// 当前玩家（人类玩家）
@property (nonatomic, strong, readonly, nullable) SPPlayer *currentPlayer;

/// 当前行动玩家
@property (nonatomic, strong, readonly, nullable) SPPlayer *activePlayer;

/// 仍在游戏中的玩家
@property (nonatomic, strong, readonly) NSArray<SPPlayer *> *activePlayers;

#pragma mark - 牌面数据

/// 牌组
@property (nonatomic, strong, readonly) SPDeck *deck;

/// 公共牌
@property (nonatomic, strong, readonly) NSArray<SPCard *> *communityCards;

/// 当前玩家手牌
@property (nonatomic, strong, readonly) NSArray<SPCard *> *playerHoleCards;

#pragma mark - 初始化方法

/**
 * 初始化游戏管理器
 * @param playerNames 玩家名称数组
 * @param aiDifficulty AI难度
 * @param smallBlind 小盲注金额
 * @param bigBlind 大盲注金额
 * @return 游戏管理器实例
 */
- (instancetype)initWithPlayerNames:(NSArray<NSString *> *)playerNames 
                       aiDifficulty:(SPAIDifficulty)aiDifficulty 
                         smallBlind:(NSInteger)smallBlind 
                           bigBlind:(NSInteger)bigBlind;

#pragma mark - 游戏控制方法

/**
 * 开始新游戏
 */
- (void)startNewGame;

/**
 * 开始新一手牌
 */
- (void)startNewHand;

/**
 * 暂停游戏
 */
- (void)pauseGame;

/**
 * 恢复游戏
 */
- (void)resumeGame;

/**
 * 结束游戏
 */
- (void)endGame;

#pragma mark - 玩家操作方法

/**
 * 玩家弃牌
 */
- (void)playerFold;

/**
 * 玩家过牌
 */
- (void)playerCheck;

/**
 * 玩家跟注
 */
- (void)playerCall;

/**
 * 玩家加注
 * @param amount 加注金额
 */
- (void)playerRaise:(NSInteger)amount;

/**
 * 玩家全下
 */
- (void)playerAllIn;

#pragma mark - 查询方法

/**
 * 检查玩家是否可以执行指定操作
 * @param action 玩家操作
 * @return 是否可以执行
 */
- (BOOL)canPlayerPerformAction:(SPPlayerAction)action;

/**
 * 获取当前需要跟注的金额
 * @return 跟注金额
 */
- (NSInteger)getCurrentCallAmount;

/**
 * 获取最小加注金额
 * @return 最小加注金额
 */
- (NSInteger)getMinRaiseAmount;

/**
 * 获取最大加注金额
 * @return 最大加注金额
 */
- (NSInteger)getMaxRaiseAmount;

/**
 * 获取玩家最佳牌型
 * @param player 玩家
 * @return 最佳牌型结果
 */
- (SPHandResult *)getBestHandForPlayer:(SPPlayer *)player;

@end

NS_ASSUME_NONNULL_END 